package com.bignerdranch.android.criminalintent;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.NavUtils;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;

public class CrimeFragment extends Fragment {
	private static final String TAG = "CrimeFragment";

	public static final String EXTRA_CRIME_ID = "com.bignerdranch.android.criminalintent.crime_id";
	private static final int REQUEST_DATE = 0;
	private static final int REQUEST_TIME = 1;
	private static final int REQUEST_TIME_OR_DATE = 2;
	private static final int REQUEST_PHOTO = 3;
	private static final int REQUEST_IMAGE_OPTION = 4;
	private static final int REQUEST_CONTACT = 5;
	private static final String DATE = "date";
	private static final String TIME = "time";
	private static final String DATE_OR_TIME = "timedate";
	private static final String DIALOG_IMAGE = "image";
	private static final String DIALOG_IMAGE_OPTION = "imageoption";

	private Crime mCrime;
	private EditText mTitleField;
	private Button mDateButton;
	private CheckBox mSolvedCheckBox;
	private ImageButton mPhotoButton;
	private ImageView mPhotoView;
	private Button mSuspectButton;
	private Callbacks mCallbacks;
	private Button mCallButton;

	public interface Callbacks {
		void onCrimeUpdated(Crime crime);
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		mCallbacks = (Callbacks) activity;
	}

	@Override
	public void onDetach() {
		super.onDetach();
		mCallbacks = null;
	}

	public static CrimeFragment newInstance(UUID crimeId) {
		Bundle args = new Bundle();
		args.putSerializable(EXTRA_CRIME_ID, crimeId);

		CrimeFragment fragment = new CrimeFragment();
		fragment.setArguments(args);
		return fragment;
	}

	@Override
	public void onPause() {
		super.onPause();
		CrimeLab.get(getActivity()).saveCrimes();
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		UUID crimeid = (UUID) getArguments().getSerializable(EXTRA_CRIME_ID);
		mCrime = CrimeLab.get(getActivity()).getCrime(crimeid);

		setHasOptionsMenu(true);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			if (NavUtils.getParentActivityName(getActivity()) != null) {
				NavUtils.navigateUpFromSameTask(getActivity());
			}
			return true;
		case R.id.menu_crime_option_delete:
			if (NavUtils.getParentActivityName(getActivity()) != null) {
				NavUtils.navigateUpFromSameTask(getActivity());
			}
			CrimeLab.get(getActivity()).deleteCrime(mCrime);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@TargetApi(11)
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// Set left arrow icon
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			if (NavUtils.getParentActivityName(getActivity()) != null) {
				getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
			}
		}

		// Set view
		View v = inflater.inflate(R.layout.fragment_crime, container, false);

		// Set elements references
		mTitleField = (EditText) v.findViewById(R.id.crime_title);
		mTitleField.setText(mCrime.getTitle());
		mDateButton = (Button) v.findViewById(R.id.crime_date);
		updateDate();
		mDateButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				FragmentManager fm = getActivity().getSupportFragmentManager();
				TimeOrDatePicketFragment dialog = new TimeOrDatePicketFragment();
				dialog.setTargetFragment(CrimeFragment.this,
						REQUEST_TIME_OR_DATE);
				dialog.show(fm, DATE_OR_TIME);
			}
		});
		mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
		mSolvedCheckBox.setChecked(mCrime.isSolved());
		mSolvedCheckBox
				.setOnCheckedChangeListener(new OnCheckedChangeListener() {
					@Override
					public void onCheckedChanged(CompoundButton buttonView,
							boolean isChecked) {
						mCrime.setSolved(isChecked);
						mCallbacks.onCrimeUpdated(mCrime);
					}
				});

		// Set listeners
		mTitleField.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence arg0, int arg1, int arg2,
					int arg3) {
				mCrime.setTitle(arg0.toString());
				mCallbacks.onCrimeUpdated(mCrime);
				getActivity().setTitle(mCrime.getTitle());
			}

			@Override
			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
				// TODO Auto-generated method stub

			}

			@Override
			public void afterTextChanged(Editable arg0) {
				// TODO Auto-generated method stub

			}
		});

		mPhotoButton = (ImageButton) v.findViewById(R.id.crime_imageButton);
		mPhotoButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent i = new Intent(getActivity(), CrimeCameraActivity.class);
				startActivityForResult(i, REQUEST_PHOTO);
			}
		});
		// Disable camera if needed
		PackageManager pm = getActivity().getPackageManager();
		if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)
				&& !pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
			mPhotoButton.setEnabled(false);
		}

		mPhotoView = (ImageView) v.findViewById(R.id.crime_imageView);
		mPhotoView.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Photo p = mCrime.getPhoto();
				if (p == null) {
					return;
				}

				FragmentManager fm = getActivity().getSupportFragmentManager();
				String path = getActivity().getFileStreamPath(p.getFileName())
						.getAbsolutePath();
				ImageFragment.getInstance(path).show(fm, DIALOG_IMAGE);

			}
		});
		mPhotoView.setOnLongClickListener(new View.OnLongClickListener() {

			@Override
			public boolean onLongClick(View v) {
				if (mCrime == null || mCrime.getPhoto() == null) {
					return false;
				}

				FragmentManager fm = getActivity().getSupportFragmentManager();
				ImageOptionsFragment dialog = new ImageOptionsFragment();
				dialog.setTargetFragment(CrimeFragment.this,
						REQUEST_IMAGE_OPTION);
				dialog.show(fm, DIALOG_IMAGE_OPTION);
				return true;
			}
		});

		Button reportButton = (Button) v.findViewById(R.id.crime_reportButton);
		reportButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_SEND);
				i.setType("text/plain");
				i.putExtra(Intent.EXTRA_TEXT, getCrimeReport());
				i.putExtra(Intent.EXTRA_TITLE,
						getString(R.string.crime_report_subject));
				i = Intent.createChooser(i, getString(R.string.send_report));

				startActivity(i);
			}
		});

		mSuspectButton = (Button) v.findViewById(R.id.crime_suspectButton);
		mSuspectButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent i = new Intent(Intent.ACTION_PICK,
						ContactsContract.Contacts.CONTENT_URI);
				startActivityForResult(i, REQUEST_CONTACT);
			}
		});
		if (mCrime.getSuspect() != null) {
			mSuspectButton.setText(mCrime.getSuspect());
		}
		
		mCallButton = (Button) v.findViewById(R.id.crime_callButton);
		mCallButton.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				try {
			        Intent callIntent = new Intent(Intent.ACTION_CALL);
			        callIntent.setData(Uri.parse("tel:" + mCrime.getPhone()));
			        startActivity(callIntent);
			    } catch (ActivityNotFoundException activityException) {
			         Log.e(TAG, "Call failed", activityException);
			    }
				
			}
		});
				
		mCallButton.setEnabled(mCrime.getPhone() != null);
		
		return v;
	}

	public void updateDate() {
		SimpleDateFormat sf = new SimpleDateFormat("cccc, MMM d, yyyy HH:mm:ss");
		mDateButton.setText(sf.format(mCrime.getDate()));
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode != Activity.RESULT_OK)
			return;
		switch (requestCode) {
		case REQUEST_TIME_OR_DATE:
			int which = data.getIntExtra(
					TimeOrDatePicketFragment.EXTRA_TIMEORDATE, -1);

			FragmentManager fm = getActivity().getSupportFragmentManager();
			switch (which) {
			case 0:
				TimePickerFragment dialog = TimePickerFragment
						.newInstance(mCrime.getDate());
				dialog.setTargetFragment(CrimeFragment.this, REQUEST_TIME);
				dialog.show(fm, TIME);
				break;
			case 1:
				DatePickerFragment dateDialog = DatePickerFragment
						.newInstance(mCrime.getDate());
				dateDialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
				dateDialog.show(fm, DATE);
				break;
			}
			break;
		case REQUEST_DATE:
			Date date = (Date) data
					.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
			mCrime.setDate(date);
			updateDate();
			mCallbacks.onCrimeUpdated(mCrime);
			break;
		case REQUEST_TIME:
			Date time = (Date) data
					.getSerializableExtra(TimePickerFragment.EXTRA_TIME);
			mCrime.setDate(time);
			updateDate();
			mCallbacks.onCrimeUpdated(mCrime);
			break;
		case REQUEST_PHOTO:
			// Create a new photo object and attach it to the crime
			String fileName = data
					.getStringExtra(CrimeCameraFragment.EXTRA_PHOTO_FILENAME);
			if (fileName != null) {
				if (mCrime.getPhoto() != null) {
					deleteImage();
				}
				Photo photo = new Photo(fileName);
				mCrime.setPhoto(photo);
				showPhoto();
			}
			mCallbacks.onCrimeUpdated(mCrime);
			break;
		case REQUEST_IMAGE_OPTION:
			int whichImageOption = data.getIntExtra(
					ImageOptionsFragment.EXTRA_OPTION, -1);

			switch (whichImageOption) {
			case 0:
				if (mCrime != null && mCrime.getPhoto() != null) {
					deleteImage();
				}
			}
			break;
		case REQUEST_CONTACT:
			Uri contactUri = data.getData();

			// Specify which values you want to query from
			String[] queryFields = new String[] { Contacts.DISPLAY_NAME };

			// Perform a query
			ContentResolver cr = getActivity().getContentResolver();
			Cursor c = cr.query(contactUri, queryFields, null, null, null);

			// Check for results
			if (c.getCount() == 0) {
				c.close();
				return;
			}

			// Pull out first row and get ata
			if (c.moveToFirst()) {
				String suspect = c.getString(0);
				mCrime.setSuspect(suspect);
				mCallbacks.onCrimeUpdated(mCrime);
				mSuspectButton.setText(suspect);

				Cursor cPhone = cr.query(
						Phone.CONTENT_URI,
						new String[] { Phone.NUMBER, Phone.TYPE },
						" DISPLAY_NAME = '"
								+ c.getString(c
										.getColumnIndex(Contacts.DISPLAY_NAME))
								+ "'", null, null);
				if (cPhone.moveToFirst()) {
					switch (cPhone.getInt(cPhone.getColumnIndex(Phone.TYPE))) {
					case Phone.TYPE_MOBILE:
					case Phone.TYPE_HOME:
					case Phone.TYPE_WORK:
					case Phone.TYPE_OTHER:
						mCrime.setPhone(cPhone.getString(cPhone.getColumnIndex(Phone.NUMBER)));
						mCallButton.setEnabled(mCrime.getPhone() != null);
						break;
					}
				}
			}
			c.close();

			break;
		}

	}

	private void deleteImage() {
		File path = getActivity().getFileStreamPath(
				mCrime.getPhoto().getFileName());
		if (path.delete()) {
			mCrime.setPhoto(null);
			showPhoto();
			Log.i(TAG, "Deleted from disk");
		}
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		super.onCreateOptionsMenu(menu, inflater);
		inflater.inflate(R.menu.crime_item_options, menu);

	}

	private void showPhoto() {
		Photo p = mCrime.getPhoto();
		BitmapDrawable b = null;

		if (p != null) {
			String path = getActivity().getFileStreamPath(p.getFileName())
					.getAbsolutePath();
			b = PictureUtils.getScaledDrawable(getActivity(), path);
		}

		mPhotoView.setImageDrawable(b);
	}

	private String getCrimeReport() {
		String solvedString = null;

		if (mCrime.isSolved()) {
			solvedString = getString(R.string.crime_report_solved);
		} else {
			solvedString = getString(R.string.crime_report_unsolved);
		}

		String dateString = DateFormat.format("EEE,  MMM dd", mCrime.getDate())
				.toString();

		String suspect = mCrime.getSuspect();
		if (suspect == null) {
			suspect = getString(R.string.crime_report_no_suspect);
		} else {
			suspect = getString(R.string.crime_report_suspect, suspect);
		}

		String report = getString(R.string.crime_report, mCrime.getTitle(),
				dateString, solvedString, suspect);
		return report;
	}

	@Override
	public void onStart() {
		super.onStart();
		showPhoto();
	}

	@Override
	public void onStop() {
		super.onStop();
		PictureUtils.cleanImageView(mPhotoView);
	}

}
